package com.example.test.controller;

import cn.hutool.core.util.StrUtil;
import com.example.test.common.ResultBody;
import com.example.test.service.ActivitiBusinessService;
import com.example.test.vo.ActivitiStartProcessVo;
import com.example.test.vo.ActivitiTaskLogVO;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ：dengjue
 * @date ：Created in 2021/7/27 20:07
 * @description ： 操作业务
 */
@RestController
@RequestMapping("activiti/business")
@Slf4j
public class ActivitiBusinessController {

    @Resource
    private RuntimeService runtimeService;
    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private ProcessEngine processEngine;
    @Resource
    private ActivitiBusinessService businessService;

    /**
     * 开启流程
     * @param vo
     */
    @PostMapping("/start")
    public ResultBody start(@Valid @RequestBody ActivitiStartProcessVo vo){
        //开启流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(vo.getProcessDefinitionKey(),vo.getBusinessKey(), vo.getMap());
        Map<String,String> map = new HashMap<>();
        map.put("processInstanceId", processInstance.getProcessInstanceId());
        return ResultBody.success(map);
    }


    /**
     * 办理流程
     * @param vo
     */
    @PostMapping("/complete")
    public ResultBody complete(@Valid @RequestBody ActivitiStartProcessVo vo){
        Task task = taskService.createTaskQuery().processDefinitionKey(vo.getProcessDefinitionKey())
                .processInstanceBusinessKey(vo.getBusinessKey()).singleResult();
        if (task != null) {
            if (StrUtil.isNotBlank(vo.getMsg())){
                taskService.addComment(task.getId(), task.getProcessInstanceId(), vo.getMsg());
            }
            taskService.complete(task.getId(), vo.getMap());
        }
        return ResultBody.success("办理成功");
    }


    /**
     * 删除流程实例
     * @param processDefinitionKey
     * @param businessKey
     * @return
     */
    @GetMapping("/delete")
    public ResultBody delete(@RequestParam("processDefinitionKey") String processDefinitionKey,
                             @RequestParam("businessKey") String businessKey){
        Task task = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey)
                .processInstanceBusinessKey(businessKey).active().singleResult();
        if (task != null) {
            runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"");
            return ResultBody.success("删除成功");
        } else {
            return ResultBody.fail("只有进行中任务才能删除");
        }
    }

    /**
     * 获取当前人待办
     * @param processDefinitionKey
     * @param userId
     */
    @GetMapping("/getHandleTask")
    public ResultBody<List<Task>> getHandleTask(@RequestParam(value = "processDefinitionKey",required = false) String processDefinitionKey,
                                                @RequestParam("userId") String userId){
        List<Task> tasks = taskService.createTaskQuery().processDefinitionKey(processDefinitionKey).taskCandidateOrAssigned(userId).list();
        return ResultBody.success(tasks);
    }

    /**
     * 获取任务办理记录
     * @param processDefinitionKey
     * @param businessKey
     * @return
     */
    @GetMapping("/queryLog")
    public ResultBody getTaskDetail(@RequestParam("processDefinitionKey") String processDefinitionKey,
                                              @RequestParam("businessKey") String businessKey){
        List<ActivitiTaskLogVO> voList = businessService.queryLog(processDefinitionKey, businessKey);
        return ResultBody.success(voList);
    }


    /**
     * 获取流程节点
     * @param processDefinitionKey
     */
    @GetMapping("/getStep")
    public ResultBody getStepByProcKey(@RequestParam("processDefinitionKey") String processDefinitionKey,
                                       @RequestParam("businessKey") String businessKey){
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processDefinitionKey(processDefinitionKey)
                .processInstanceBusinessKey(businessKey).singleResult();
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstance.getId()).orderByActivityId().asc().list();
        return ResultBody.success(list);
    }


    /**
     * 流程视图
     * @param resp
     * @param processDefinitionKey
     * @throws Exception
     */
    @GetMapping("/pic")
    public void showPic(HttpServletResponse resp, @RequestParam("processDefinitionKey") String processDefinitionKey,
                        @RequestParam("businessKey") String businessKey) throws Exception {
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processDefinitionKey(processDefinitionKey)
                .processInstanceBusinessKey(businessKey).singleResult();
        if (pi == null) {
            resp.setContentType("text/html;charset=UTF-8");
            resp.getWriter().write("任务已结束");
            return;
        }
        List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(pi.getProcessInstanceId()).list();
        List<String> activityIds = new ArrayList<>();
        List<String> flows = new ArrayList<>();
        for (Execution exe : executions) {
            List<String> ids = runtimeService.getActiveActivityIds(exe.getId());
            activityIds.addAll(ids);
        }
        //生成流程图
        BpmnModel bpmnModel = repositoryService.getBpmnModel(pi.getProcessDefinitionId());
        ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
        ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
        InputStream in = diagramGenerator.generateDiagram(bpmnModel, "png", activityIds, flows,
                engconf.getActivityFontName(), engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0);
        OutputStream out = null;
        byte[] buf = new byte[1024];
        int legth = 0;
        try {
            out = resp.getOutputStream();
            while ((legth = in.read(buf)) != -1) {
                out.write(buf, 0, legth);
            }
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }
}
